package memory;

interface ObjectFactory {
        public Object makeObject();
    }

    public class MemoryTestBench {
        public static long calculateMemoryUsage(ObjectFactory factory) {
            Object handle = factory.makeObject();
            long mem0 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
            long mem1 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
            handle = null;
            System.gc(); System.gc(); System.gc(); System.gc();
            System.gc(); System.gc(); System.gc(); System.gc();
            System.gc(); System.gc(); System.gc(); System.gc();
            System.gc(); System.gc(); System.gc(); System.gc();
            mem0 = Runtime.getRuntime().totalMemory() -
                    Runtime.getRuntime().freeMemory();
            handle = factory.makeObject();
            System.gc(); System.gc(); System.gc(); System.gc();
            System.gc(); System.gc(); System.gc(); System.gc();
            System.gc(); System.gc(); System.gc(); System.gc();
            System.gc(); System.gc(); System.gc(); System.gc();
            mem1 = Runtime.getRuntime().totalMemory() -
                    Runtime.getRuntime().freeMemory();
            return mem1 - mem0;
        }

        public static void showMemoryUsage(ObjectFactory factory) {
            long mem = calculateMemoryUsage(factory);
            System.out.println(
                    factory.getClass().getName() + " produced " +
                            factory.makeObject().getClass().getName() +
                            " which took " + mem + " bytes");
        }

        public static void main(String[] args) {
                   showMemoryUsage(new BooleanArrayFactory());
        }
    }

    class ByteFactory implements ObjectFactory {
        public Object makeObject() {
            return new Byte((byte)33);
        }
    }

    class ThreeByteFactory implements ObjectFactory {
        public Object makeObject() {
            return new ThreeBytes();
        }

        private static class ThreeBytes {
            byte b0, b1, b2;
        }

}

class SixtyFourBooleanFactory implements ObjectFactory {
    public Object makeObject() {
        return new SixtyFourBooleans();
    }

    private static class SixtyFourBooleans {
        boolean a0, a1, a2, a3, a4, a5, a6, a7;
        boolean b0, b1, b2, b3, b4, b5, b6, b7;
        boolean c0, c1, c2, c3, c4, c5, c6, c7;
        boolean d0, d1, d2, d3, d4, d5, d6, d7;
        boolean e0, e1, e2, e3, e4, e5, e6, e7;
        boolean f0, f1, f2, f3, f4, f5, f6, f7;
        boolean g0, g1, g2, g3, g4, g5, g6, g7;
        boolean h0, h1, h2, h3, h4, h5, h6, h7;
    }
}
    class BooleanArrayFactory implements ObjectFactory {
        public Object makeObject() {
            Boolean[] objs = new Boolean[1000];
            for (int i=0; i<objs.length; i++)
                objs[i] = new Boolean(true);
            return objs;
        }
 }


